﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AIProject.Search;

namespace AIProject.AI
{
    class AlphaBetaGameAgent : GameAgent
    {
        private Boolean isWhite;
        private AlphaBeta ab;
        private NodeInfo nodeInfo;

        public int Nodes
        {
            get
            {
                return (ab.NodeCount + ab.ExtNodes);
            }
            set
            {
            }
        }

        public AlphaBetaGameAgent(Boolean isWhite)
        {
            this.isWhite = isWhite;
        }

        public Pylos.Action getAction(Percept p)
        {
            Pylos.Action minAction = null;
            Pylos.Action maxAction = null;

            nodeInfo = new NodeInfo(4, isWhite);
            ab = new AlphaBeta(nodeInfo, 4);

            Node root = new Node(p.State);
            List<Pylos.Action> actions = p.State.getActions();

            double alpha = Double.NegativeInfinity;
            double beta = Double.PositiveInfinity;
            double childValue;

            if (actions.Count == 0)
            {
                return null;
            }

            foreach (Pylos.Action arc in actions)
            {
                Node child = (Node)root.clone();
                child.update(arc);

                if (this.isWhite)
                {
                    if (nodeInfo.isTerminal(child)
                            || child.State.getActions().Count == 0
                            || child.Cost >= nodeInfo.DepthLimit)
                    {
                        childValue = nodeInfo.utility(child);
                        ab.NodeCount++;
                    }
                    else
                    {
                        childValue = ab.minValue(child, alpha, beta, false, false);
                    }

                    if (childValue >= alpha)
                    {
                        alpha = childValue;
                        maxAction = arc;
                    }
                }
                else
                {
                    if (nodeInfo.isTerminal(child)
                            || child.State.getActions().Count == 0
                            || child.Cost >= nodeInfo.DepthLimit)
                    {
                        ab.NodeCount++;
                        childValue = nodeInfo.utility(child);
                    }
                    else
                    {
                        childValue = ab.maxValue(child, alpha, beta, false, false);
                    }

                    if (childValue <= beta)
                    {
                        beta = childValue;
                        minAction = arc;
                    }
                }
            }
            Console.WriteLine(ab.NodeCount + " and ext Nodes " + ab.ExtNodes);

            return (isWhite ? maxAction : minAction);
        }
    }
}
